package websocket

import (
	"encoding/json"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/websocket"
)

const (
	// 写入等待时间
	writeWait = 10 * time.Second

	// 读取下一个pong消息的等待时间
	pongWait = 60 * time.Second

	// 发送ping消息的间隔，必须小于pongWait
	pingPeriod = (pongWait * 9) / 10

	// 最大消息大小
	maxMessageSize = 512
)

var upgrader1 = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		// 允许所有来源，生产环境应该限制
		return true
	},
}

// Client 是WebSocket客户端和Hub之间的中间人
type Client struct {
	// Hub的引用
	hub *Hub

	// WebSocket连接
	conn *websocket.Conn

	// 发送消息的缓冲通道
	send chan []byte

	// 用户ID
	UserID string
}

// Message 消息结构
type Message struct {
	Type    string      `json:"type"`
	Data    interface{} `json:"data"`
	UserID  string      `json:"user_id,omitempty"`
	OrderID uint64      `json:"order_id,omitempty"`
}

// OrderUpdate 订单更新消息
type OrderUpdate struct {
	OrderID       uint64  `json:"order_id"`
	OrderNo       string  `json:"order_no"`
	Status        int32   `json:"status"`
	PaymentStatus int32   `json:"payment_status"`
	TotalAmount   float64 `json:"total_amount"`
	UpdatedAt     string  `json:"updated_at"`
}

// readPump 从WebSocket连接读取消息
func (c *Client) readPump() {
	defer func() {
		c.hub.unregister <- c
		c.conn.Close()
	}()

	c.conn.SetReadLimit(maxMessageSize)
	c.conn.SetReadDeadline(time.Now().Add(pongWait))
	c.conn.SetPongHandler(func(string) error {
		c.conn.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})

	for {
		_, message, err := c.conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("WebSocket错误: %v", err)
			}
			break
		}

		// 处理接收到的消息
		c.handleMessage(message)
	}
}

// writePump 向WebSocket连接写入消息
func (c *Client) writePump() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.conn.Close()
	}()

	for {
		select {
		case message, ok := <-c.send:
			c.conn.SetWriteDeadline(time.Now().Add(writeWait))
			if !ok {
				c.conn.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}

			w, err := c.conn.NextWriter(websocket.TextMessage)
			if err != nil {
				return
			}
			w.Write(message)

			// 添加队列中的消息
			n := len(c.send)
			for i := 0; i < n; i++ {
				w.Write([]byte{'\n'})
				w.Write(<-c.send)
			}

			if err := w.Close(); err != nil {
				return
			}
		case <-ticker.C:
			c.conn.SetWriteDeadline(time.Now().Add(writeWait))
			if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
				return
			}
		}
	}
}

// handleMessage 处理接收到的消息
func (c *Client) handleMessage(message []byte) {
	var msg Message
	if err := json.Unmarshal(message, &msg); err != nil {
		log.Printf("解析消息错误: %v", err)
		return
	}

	switch msg.Type {
	case "ping":
		// 响应ping消息
		response := Message{
			Type: "pong",
			Data: "pong",
		}
		responseData, _ := json.Marshal(response)
		c.send <- responseData

	case "subscribe_orders":
		// 订阅订单更新
		log.Printf("用户 %s 订阅订单更新", c.UserID)

	case "unsubscribe_orders":
		// 取消订阅订单更新
		log.Printf("用户 %s 取消订阅订单更新", c.UserID)

	default:
		log.Printf("未知消息类型: %s", msg.Type)
	}
}

// ServeWS 处理WebSocket升级请求
func ServeWS(hub *Hub, w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader1.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("WebSocket升级失败: %v", err)
		return
	}

	// 从查询参数获取用户ID，如果没有提供则使用默认值
	userID := r.URL.Query().Get("user_id")
	if userID == "" {
		userID = "default_user"
		log.Printf("未提供用户ID参数，使用默认用户: %s", userID)
	}

	client := &Client{
		hub:    hub,
		conn:   conn,
		send:   make(chan []byte, 256),
		UserID: userID,
	}
	client.hub.register <- client

	// 启动goroutine处理读写
	go client.writePump()
	go client.readPump()
}
